import analysis.grammaticalAnalysis.GramMain;
import analysis.lexicalAnalysis.LexMain;
import utils.CommonUtils;

import java.io.*;
import java.lang.reflect.Array;
import java.nio.charset.StandardCharsets;
import java.util.*;

/**
 * 主类
 */
public class Main {

    private static final Scanner scan;

    // 状态转化变量
    private static String[] chList;
    // 从左到右，第一个key代表行(转换前的状态)，
    // 第二个key代表列(状态转换的变量)，
    // 第二个value代表表项(转换后的状态)
    private static Map<String, Map<String, ArrayList<String>>> statusMap;

    // 词法分析·开始状态
    private static List<String> LexicalStartStatus = null;

    // 词法分析·结束状态
    private static List<String> LexicalEndStatus = null;

    private static Map<String, ArrayList<String>> grammarMap = null;

    // 语法分析·开始状态
    private static String grammarStartStatus = null;

    //静态代码块用来初始化一些参数
    static {
        scan = new Scanner(System.in);
        readStatusChangeFile("source/test/lexicalTest/StatusChangeFirst.txt");
        readGrammarFile("source/test/grammaticalTest/grammarTest1.txt");
        System.out.println("+-----------------------------------+");
        CommonUtils.printMap("|Main:static{}: statusMap:" ,statusMap);
        System.out.println("|Main:static{}: LexicalStartStatus:" + LexicalStartStatus + " LexicalEndStatus:" + LexicalEndStatus);
        CommonUtils.printMap("|Main:static{}: grammarMap:" ,grammarMap);
        System.out.println("+-----------------------------------+");
    }

    public static void main(String[] args){
        System.out.println("+-----------------------------------+");
        System.out.println("|---------请选择要测试的项目----------|");
        System.out.println("+-----------------------------------+");
        System.out.println("|-----------1、词法分析--------------|");
        System.out.println("+-----------------------------------+");
        System.out.println("|-----------2、语法分析--------------|");
        System.out.println("+-----------------------------------+");
        System.out.println("|-----------0、退    出--------------|");
        System.out.println("+-----------------------------------+");
        int itemChoose = -1;
        while (itemChoose != 0){
            System.out.print("\\-> ");
            try{
                itemChoose = Integer.parseInt(scan.next());
                switch (itemChoose){
                    case 0:{
                        System.out.println("|Main:main(): 退出中...");
                        break;
                    }
                    case 1:{
                        LexMain lexMain = new LexMain(chList, statusMap, LexicalStartStatus, LexicalEndStatus);
                        lexMain.lexMain();
                        System.out.println("|LexMain:lexMain(): 返回成功...");
                        itemChoose = -1;
                        break;
                    }
                    case 2:{
                        GramMain gramMain = new GramMain(grammarMap, grammarStartStatus);
                        gramMain.gramMain();
                        itemChoose = -1;
                        break;
                    }
                    default:{
                        System.out.println("|Main:main(): 输入不匹配，5");
                    }
                }
            } catch (NumberFormatException numberFormatException){
                System.out.println("|Main:main(): 输入不匹配，请重新输入");
            } catch (NoSuchElementException noSuchElementException){
                System.out.println("|Main:main(): 输入为空");
            }
        }
        scan.close();
    }

    /**
     * 读取状态转换表
     */
    public static void readStatusChangeFile(String sourcePath){
        File statusChangeFile = new File(sourcePath);
        FileInputStream fis = null;
        InputStreamReader isr = null;
        BufferedReader br = null;
        try {
            fis = new FileInputStream(statusChangeFile);
            isr = new InputStreamReader(fis, StandardCharsets.UTF_8);
            br = new BufferedReader(isr);
            String line;
            boolean isFirstLine = true;
            statusMap = new HashMap<>();
            String status = null;
            while((line = br.readLine()) != null){
                if(line.length() > 0){  // 该行不能为空，为空直接跳过
                    if(isFirstLine){    // 读取表头
                        chList = line.split("\\s+");
                        isFirstLine = false;
                    }else{  //读取每一行的状态转换行
                        int changeLen = chList.length;
                        Map<String, ArrayList<String>> statusChanged;
                        // 包含第一列和后面的状态
                        String[] statusAndChangedStatus = line.split("\\s+");
                        if(":".equals(statusAndChangedStatus[1])){
                            // 获取状态转换的开始状态和结束状态
                            if("startStatus".equals(statusAndChangedStatus[0])){    // 开始状态
                                LexicalStartStatus = Arrays.asList(statusAndChangedStatus[2].split(","));
                            } else if ("endStatus".equals(statusAndChangedStatus[0])){  // 结束状态
                                LexicalEndStatus = Arrays.asList(statusAndChangedStatus[2].split(","));
                            }else {
                                System.out.println("|Main:readFile(): check [startStatus/endStatus] input...");
                            }

                        } else {    // 正常的表项
                            // 每次都获取状态，等结束的时候可以直接就是末尾的状态
                            status = statusAndChangedStatus[0];
                            // 拷贝出后面的状态变化
                            String[] changedStatus = Arrays.copyOfRange(statusAndChangedStatus, 1, changeLen + 1);
                            statusChanged = new HashMap<>();
                            for(int i = 0; i < changeLen; i++){
//                        System.out.println("chList[" + i + "] = " + chList[i] + " changeLen=" + changeLen);
                                String[] strValues = changedStatus[i].split(",");
                                // 解析出每个表项的具体数值
                                // 获取当前第i行的状态变化map， 不含变化前状态
                                statusChanged.put(chList[i], new ArrayList<>(Arrays.asList(strValues)));
//                        System.out.println("Main:readFile:statusChanged: " + statusChanged + " i=" + i);
                            }
                            // 获取当前第i行的状态变化map，含变化前状态
                            statusMap.put(statusAndChangedStatus[0], statusChanged);
//                            CommonUtils.printMap("|Main:readFile():statusMap" ,statusMap);
                        }
                    }
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if(br != null){
                try {
                    br.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(isr != null){
                try {
                    isr.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(fis != null){
                try {
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 读取语法分析的文件
     * @param sourcePath 文件路径
     */
    public static void readGrammarFile(String sourcePath){
        File statusChangeFile = new File(sourcePath);
        FileInputStream fis = null;
        InputStreamReader isr = null;
        BufferedReader br = null;
        try {
            fis = new FileInputStream(statusChangeFile);
            isr = new InputStreamReader(fis, StandardCharsets.UTF_8);
            br = new BufferedReader(isr);
            grammarMap = new HashMap<>();
            String line;
            boolean isFirstLine = true;
            while((line = br.readLine()) != null){
                if(line.length() > 0){  // 该行不能为空，为空直接跳过
                    String[] production = line.split("\\s+");
                    if( !"→".equals(production[1]) || production.length < 3){   // 输入检测
                        System.out.println("|Main:readGrammarFile(): 产生式输入错误...");
                        continue;
                    }
                    if(isFirstLine){
                        grammarStartStatus = production[0];
                        isFirstLine = false;
                    }
                    List<String> productionRight = Arrays.asList(production[2].split("\\|"));
                    ArrayList<String> productRightList;
                    if(grammarMap.containsKey(production[0])){
                        productRightList = grammarMap.get(production[0]);
                    } else{
                        productRightList = new ArrayList<>();
                    }
                    productRightList.addAll(productionRight);
                    grammarMap.put(production[0], productRightList);
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if(br != null){
                try {
                    br.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(isr != null){
                try {
                    isr.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(fis != null){
                try {
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
